package cn.edu.zju.om.analyse;

import java.io.FileWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.text.Position;

import cn.edu.zju.om.data.Comment;
import cn.edu.zju.om.data.DAO;
import cn.edu.zju.om.data.ReviewTarget;
import cn.edu.zju.om.nlp.PosTagger;
import cn.edu.zju.om.nlp.SUPosTaggerAdapter;
import cn.edu.zju.om.nlp.TaggedWord;

public class PhraseExtractor implements CommentProcessor {
	
	private Map<String, Phrase> phrases;
	
	private static PosTagger tagger;
	
	public PhraseExtractor() throws Exception {
		if (tagger == null) {
			tagger = new SUPosTaggerAdapter();
		}
		
		phrases = new HashMap<String, Phrase>();
	}

	public void process(Comment comment) {
		float rating = comment.getMark();
		
		List<String> words = comment.getSeggedWords();
		
		List<TaggedWord> taggedWords = tagger.tagWordList(words);
		
		for(int i = 0; i < taggedWords.size(); ++i) {
			TaggedWord modifierWord = taggedWords.get(i);
			
			if (modifierWord.getTag().equals("VA")) {
				int left = searchLeft(taggedWords, i);
				
				int right = searchRight(taggedWords, i);
				
				int headTermIndex;
				if (left == right) {
					// no found on both side
					continue;
				} else if (left == -1 && right != -1) {
					headTermIndex = right;
				} else if (left != -1 && right == -1) {
					headTermIndex = left;
				} else {
					// pick the nearer one
					int leftRange = i - left;
					int rightRange = right - i;
					
					if (leftRange < rightRange) {
						headTermIndex = left;
					} else {
						headTermIndex = right;
					}
				}
				
				String headTermName = taggedWords.get(headTermIndex).getWord();
				String modifierName = modifierWord.getWord();
				
				Phrase phrase = phrases.get(headTermName);
				if (phrase == null) {
					phrase = new Phrase(headTermName, modifierName, rating);
					phrases.put(headTermName, phrase);
				} else {
					phrase.update(modifierName, rating);
				}
			}
		}
	}
	
	
	public Map<String, Phrase> getPhrases() {
		return phrases;
	}
	
	public void reSet() {
		phrases.clear();
	}

	private int searchRight(List<TaggedWord> taggedWords, int i) {
		int right = -1;
		for (int j = i + 1; j < taggedWords.size(); ++j) {
			String tag = taggedWords.get(j).getTag();
			if (tag.equals("NN")) {
				right = j;
				break;
			}
			else if (tag.equals("PU")) {
				break;
			}
		}
		return right;
	}

	private int searchLeft(List<TaggedWord> taggedWords, int i) {
		int left = -1;
		for (int j = i - 1; j >= 0; --j) {
			String tag = taggedWords.get(j).getTag();
			if (tag.equals("NN")) {
				left = j;
				break;
			}
			else if (tag.equals("PU")) {
				break;
			}
		}
		return left;
	}

	
	public static void main(String[] args) throws Exception {
		PhraseExtractor extractor = new PhraseExtractor();
		
		DAO<ReviewTarget, String> reviewTargetDAO = new DAO<ReviewTarget, String>(ReviewTarget.class);
		//List<ReviewTarget> targets = reviewTargetDAO.findAll();
		
		List<ReviewTarget> targets = new ArrayList<ReviewTarget>();
		
		targets.add(reviewTargetDAO.findById("8acc80c42663694c01266369d822000a", false));
		
		for(ReviewTarget target : targets) {
			Writer writer = new FileWriter("out\\" + /*"allComments"*/target.getName() + ".txt");
			
			Set<Comment> comments = target.getComments();
		//DAO<Comment, String> commentsDAO = new DAO<Comment, String>(Comment.class);
		//List<Comment> comments = commentsDAO.findAll();
			
			for(Comment comment : comments) {
				extractor.process(comment);
			}
			
			Map<String, Phrase> phrases = extractor.getPhrases();
			
			
			//////////////////////////////////////////////
			
			
//			for(Phrase phrase : phrases.values()) {
//				writer.write(phrase.toString());
//				writer.write("\r\n");
//			}
//			
			
			
			
			//////////////////////////////////////////////
			
			Map<String, Integer> modifierTable = new HashMap<String, Integer>();
			int indexNumber = 0;
			Iterator<Entry<String, Phrase>> it = phrases.entrySet().iterator();
			while (it.hasNext()) {
				Phrase phrase = it.next().getValue();
				if (phrase.getCount() > 10) {
					Map<String, Modifier> modifiers = phrase.getModifiers();
					
					for(String modifierName : modifiers.keySet()) {
						if(!modifierTable.containsKey(modifierName)) {
							modifierTable.put(modifierName, new Integer(indexNumber++));
						}
					}
				} else {
					it.remove();
				}
			}
			
			FeatureVectorFactory factory = new FeatureVectorFactory();
			List<PhraseFeatureVector> featureVectors = factory.buildFeatureVectors(phrases);
			
			KMeansCluster cluster = new KMeansCluster(featureVectors, 5, 500);
			
			List<PhraseGroup> groups = cluster.caculateClusters();
			
			for(PhraseGroup group : groups) {
				writer.write("\r\n{\r\n");
				writer.write(group.toString());
				writer.write("\r\n}\r\n");
			}
			
			extractor.reSet();
			writer.close();
		}
		

	}

}
